# -*- coding: utf-8 -*-
import re
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication , QMainWindow
from Ui_pd import Ui_MainWindow

class MyMainWindow(QMainWindow, Ui_MainWindow):
    i = 0
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
            print("回车键被按下")
            self.write_data()
        if event.key() == Qt.Key_Escape:
            self.close()
        else:
            super().keyPressEvent(event)
    def get_dataobj_content(self):
        pdo_str = self.line_edit_data_obj.text()
        pdo_str = re.split(r"[,\s]+", pdo_str)
        print(pdo_str)
        pdo = []
        for s in pdo_str:
            try:
                num = int(s, 16)
                pdo.append(num)
            except ValueError:
                print("Invalid input")
            print(hex(num))
        return pdo


    def write_data(self):
        self.text_parsed_data.clear()
        header = self.line_edit_msg_header.text()
        print(header)
        try:
            hex_data = int(header, 16)
            print(hex_data)

            extended = (hex_data >> 15) & 1
            parsed_str =    "Extended .......................... " + str(extended)  + '\n'
            ndo = (hex_data >> 12) & 7
            parsed_str = parsed_str + "Number of Data Objects ............ " + str(ndo) + '\n'
            msgid = (hex_data >> 9) & 7
            parsed_str = parsed_str + "Message ID ........................ " + str(msgid) + '\n'
            pwr_role = (hex_data >> 8) & 1
            parsed_str = parsed_str + "Power Role ........................ " + str(pwr_role) + '\n'
            spec_rev = (hex_data >> 6)  & 3
            parsed_str = parsed_str + "Specification Revision ............ " + str(spec_rev) + '\n'
            data_role = (hex_data >> 5) & 1
            parsed_str = parsed_str + "Data Role ......................... " + str(data_role) + '\n'
            msg_type = (hex_data >> 0) & 0x1f
            ctrl_msg = {
                1: 'GoodCRC',
                2: 'GotoMin',
                3: 'Accept',
                4: 'Reject',
                5: 'Ping',
                6: 'PS_RDY',
                7: 'Get_Source_Cap',
                8: 'Get_Sink_Cap',
                9: 'DR_Swap',
                0xa: 'PR_Swap',
                0xb: 'VCONN_Swap',
                0xc: 'Wait',
                0xd: 'Soft_Reset',
                0xe: 'Data_Reset',
                0xf: 'Data_Reset_Complete',
                0x10: 'Not_Support',
                0x11: 'Get_Source_cap_extended',
                0x12: 'Get_Status',
                0x13: 'FR_Swap',
                0x14: 'Get_PPS_Status',
                0x15: 'Get_Country_Code',
                0x16: 'Get_Sink_Cap_extended',
                0x17: 'Get_Source_Info',
                0x18: 'Get_Revision'}

            data_msg = {
                1: 'Source_Capabilities',
                2: 'Request',
                3: 'BIST',
                4: 'Sink_Capabilities',
                5: 'Battery_Status',
                6: 'Alert',
                7: 'Get_Country_Info',
                8: 'Enter_USB',
                9: 'EPR_Request',
                10: 'EPR_Mode',
                11: 'Source_Info',
                12: 'Revision',
                15: 'Vendor_Defined'}
            if (extended == 0):
                if (ndo == 0): # ctrl msg
                    msg_type_str =  ctrl_msg[msg_type] if msg_type in ctrl_msg else 'Reserved'
                    parsed_str = parsed_str + "Message Type ...................... {}\n" .format(msg_type_str)
                else :
                    msg_type_str = data_msg[msg_type] if msg_type in data_msg else "Reserved"
                    parsed_str = parsed_str + "Message Type ...................... {}\n" .format(msg_type_str)
                    print("data message")
                    if (msg_type_str == "Vendor_Defined"):
                        print("vdm message")
                        vdm_data = self.get_dataobj_content()
                        vdm_header = (vdm_data[0] >> 16) & 0xffff
                        i = 0
                        vdm_data_obj = [0,0,0,0,0,0,0]
                        parsed_str += "\tVdm Header ........................ {}\n".format(hex(vdm_header))
                        parsed_str += "\tVdm Data .......................... "
                        while i < (len(vdm_data) - 1):
                            vdm_data_obj[i] = ((vdm_data[i] << 16) & 0xffff0000) + ((vdm_data[i + 1] >> 16) & 0xffff)
                            print(hex(vdm_data_obj[i]))
                            parsed_str += hex(vdm_data_obj[i]) + "\n\t         .......................... "
                            i += 1
                        vdm_data_obj[i] = (vdm_data[i] << 16) & 0XFFFF0000
                        print('\n')
                        parsed_str += hex(vdm_data_obj[i])
                    elif (msg_type_str ==  "Request"):
                        # 1042 1004b12c
                        req = self.get_dataobj_content()[0]
                        print(req)
                        obj_pos = (req >> 28) & 0b111
                        parsed_str += "\tObject position ................... {}\n".format(str(obj_pos))
                        give_back = (req >> 27) & 1
                        parsed_str += "\tGiveBack flag ..................... {}\n".format(str(give_back))
                        capa_mismatch = (req >> 26) & 1
                        parsed_str += "\tCapability Mismatch ............... {}\n".format(str(capa_mismatch))
                        comm = (req >> 25) & 1
                        parsed_str += "\tUSB Communications Capable ........ {}\n".format(str(comm))
                        suspend = (req >> 24) & 1
                        parsed_str += "\tNo USB Suspend .................... {}\n".format(str(suspend))
                        unchunked = (req >> 23) & 1
                        parsed_str += "\tUnchunked Extended Messages Supported {}\n".format(str(suspend))
                        epr_capable = (req >> 22) & 1
                        parsed_str += "\tEPR Mode Capable .................. {}\n".format(str(epr_capable))
                        op_curr = ((req >> 10) & 0b1111111111) * 10
                        parsed_str += "\t[If PDO is Fixed]\n"
                        parsed_str += "\tOperating current ................. {}\n".format(str(op_curr))
                        max_curr = (req & 0b1111111111) * 10
                        parsed_str += "\tOperating current ................. {}\n".format(str(max_curr))
                        parsed_str += "\t[If PDO is PPS]\n"
                        volt = ((req >> 9) & 0b111111111111) * 20
                        parsed_str += "\tOutput Voltage .................... {}\n".format(str(volt))
                        curr = (req & 0b1111111) * 50
                        parsed_str += "\tOperating current ................. {}\n".format(str(curr))
                        parsed_str += "\t[If PDO is AVS]\n"
                        volt = ((req >> 9) & 0b111111111111) * 25
                        parsed_str += "\tOutput Voltage .................... {}\n".format(str(volt))
                        curr = (req & 0b1111111) * 50
                        parsed_str += "\tOperating current ................. {}\n".format(str(curr))

                    elif (msg_type_str == "Source_Capabilities"):
                        pdo = self.get_dataobj_content()
                        pdo_idx = 0
                        for num in pdo:
                            parsed_str = parsed_str + "PDO[{}]".format(pdo_idx) + '\n'
                            print(hex(num))
                            if ((num >> 30) & 3) == 0:
                                parsed_str = parsed_str + "\tPower Type ........................ Fixed Supply\n"
                                if (pdo_idx == 0):
                                    drp = (num >> 29) & 1
                                    parsed_str = parsed_str + "\tDual-Role Power ................... " + str(drp) + '\n'
                                    suspend = (num >> 28) & 1
                                    parsed_str = parsed_str + "\tUSB Suspend Support................ " + str(suspend) + '\n'
                                    unconstrained = (num >> 27) & 1
                                    parsed_str = parsed_str + "\tUnconstrained Power ............... " + str(unconstrained) + '\n'
                                    communication = (num >> 26) & 1
                                    parsed_str = parsed_str + "\tUSB Communications Capable ........ " + str(communication) + '\n'
                                    drd = (num >> 25) & 1
                                    parsed_str = parsed_str + "\tDual-Role Data .................... " + str(drd) + '\n'
                                    unchunked = (num >> 24) & 1
                                    parsed_str = parsed_str + "\tUnchunked Extended Messages Support " + str(unchunked) + '\n'
                                    epr_support = (num >> 23) & 1
                                    parsed_str = parsed_str + "\tEPR Mode Capable .................. " + str(epr_support) + '\n'
                                    peak_curr = (num >> 20) & 3
                                    parsed_str = parsed_str + "\tPeak Current ...................... " + str(peak_curr) + '\n'
                                volt = ((num >> 10) & 0b1111111111) * 50
                                parsed_str = parsed_str + "\tVoltage ........................... " + str(volt) + 'mV\n'
                                curr = (num  & 0b1111111111) * 10
                                parsed_str = parsed_str + "\tCurrent ........................... " + str(curr) + 'mA\n'


                            if ((num >> 30) & 3) == 1:
                                parsed_str = parsed_str + "\tPower Type ........................ non-Battery Supply\n"
                                # TODO: not support currently
                            if ((num >> 30) & 3) == 2:
                                parsed_str = parsed_str + "\tPower Type ........................ Battery Supply\n"
                                # TODO: not support currently
                            if ((num >> 30) & 3) == 3:
                                parsed_str = parsed_str + "\tPower Type ........................ PPS Supply\n"
                                apdo_type = (num >> 28) & 3
                                if (apdo_type == 0):
                                    parsed_str = parsed_str + "\tPPS Type .......................... SPR\n"
                                if (apdo_type == 1):
                                    parsed_str = parsed_str + "\tPPS Type .......................... EPR\n"
                                peak_curr = (num >> 27) & 1
                                parsed_str = parsed_str + "\tPPS Power Limit ................... {}\n".format(str(peak_curr))
                                max_volt = ((num >> 17) & 0b11111111) * 100
                                parsed_str = parsed_str + "\tMax Voltage ....................... {}mV\n".format(str(max_volt))
                                min_volt = ((num >> 8) & 0b11111111) * 100
                                parsed_str = parsed_str + "\tMax Voltage ....................... {}mV\n".format(str(min_volt))
                                max_curr = (num & 0b1111111) * 50
                                parsed_str = parsed_str + "\tMax Current ....................... {}mA\n".format(str(max_curr))
                            pdo_idx = pdo_idx + 1

            else:
                ext_msg = {
                1: 'Source_Cap_Extended',
                2: 'Status',
                3: 'Get_Battery_Cap',
                4: 'Get_Battery_Status',
                5: 'Battery_Cap',
                6: 'Get_Manufacturer_Info',
                7: 'Manufacturer_Info',
                8: 'Security_Request',
                9: 'Security_Response',
                10: 'Firmware_Update_Request',
                11: 'Firmware_Update_Response',
                12: 'PPS_Status',
                13: 'Country_Info',
                14: 'Country_Codes'}
                ext_type = ext_msg[msg_type] if msg_type in ext_msg else 'Reserved'
                parsed_str = parsed_str + "Message Type ...................... ext. {}\n".format(ext_type)
                parsed_str = parsed_str + 'Extended Header\n'
                data_obj = self.get_dataobj_content()
                print(data_obj)
                # TODO: extended header not support yet
            self.text_parsed_data.appendPlainText(parsed_str)
        except ValueError:
            self.text_parsed_data.appendPlainText("Input value invalid!")
        # self.text_pased_data.appendPlainText(header + str(self.i))
        # self.text_pased_data.appendPlainText(header)

import os
if __name__=="__main__":
    os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1'
    app = QApplication(sys.argv)
    myWin = MyMainWindow()
    myWin.show()
    sys.exit(app.exec_())
